デモ
(実演タイム)
(CLANのチュートリアル動画作りました。
この動画での2:00~6:00相当の内容を Kyoto.lisp TT #2 にて実演しました。)
これは何?
- これは、自分が作ったCLANというもの
- CLANは、Android向けアプリ構築キット
- 大雑把に言うと、Java用のゲーム構築ライブラリであるLibGDXと、JVM向けLisp処理系であるClojureを、一緒に使えるようにしたもの
LibGDXって何?
- 日本では全然流行ってないが、英語圏ではそこそこ人気があるゲーム構築ライブラリ
- 一時期話題になった「Ingress」(実世界の地図情報とGPS情報を利用したオンライン陣取りゲーム、Google製)もLibGDXを使っている
↓
もうちょっと詳しく!
- LibGDXは、同じソースから、JREインストール済のPC(Windows, Mac, Linux, *BSD, etc...)、Android、iOS、html5のそれぞれに対するデプロイができる
- OpenGL(ES)を使って、一枚のスクリーンを毎フレーム更新していくタイプ。
各OSの標準のGUI等は基本使わない → ゲーム向き
- 他の、Androidデプロイ可能なゲーム用フレームワークよりも速度面で優れている、らしい
- 日本語のドキュメントや記事さえあれば日本でももっと流行ると思う
↓
もっと知りたい!
- LibGDXの開発者が書いたAndroidゲームプログラミング A to Z(amazon)という本がある。
これはLibGDXそのものの解説書ではないものの、これを読めば、LibGDXも含めたAndroid向けゲーム作成の概要が分かる。
良著、ただし2011年の本なのでちょっと情報が古くなっている。
- LibGDX公式サイトにJavadoc、Wiki、Forumがあり、どれもまめに更新されている。もちろん英語。
- 自分以外にもLibGDXを試して日本語でブログ記事を書いてる人が数人ぐらいいるので、ぐぐってみる
問題?
- 気分よくClojureで普通にコード書いてPC上で問題なく動いた。しかしAndroid実機で動かしたらすごいガクガクしてまともに遊べない
↓
どう解決したの?
以下を満たす事で、実機でもフレームレートが改善した
(手元の端末ではほぼ60を達成)
- フレーム毎のrender()メソッド内ではオブジェクト生成をしてはならない。生成するとGCが動いてフレームレート大幅低下
- 外部メソッドおよび関数呼び出しはDalvik VM上ではそこそこのコストがかかる。のでフレーム毎のrender()メソッド内では、可能な限りこれらの回数を少なくする
↓
解決したんだ。よかったね。
よくない。
関数型言語としてのClojureちゃんが息してない
- Clojureのimmutableなデータ型が使えない
(使うとGC発生)
- mapやreduce(いわゆるfold)が使えない
(中で毎回関数呼び出しが発生するのと、中でconsしてるのでGC発生源になる)
- Clojureは関数指向言語である前にLispなので、マクロを使えばある程度DSL化ができる。
とは言うもののcons類もmap類も封じられると非常にきつい
じゃあどうするの?
以下からどれかを選択する。
↓
選択肢#1
- Android向けは諦める。
PC向けだけにする。
そして普通にClojure的なコードを書いて楽に開発する。
PC上で動かす分には、普通のClojure流儀のコードを書いても良好なパフォーマンスが出る。
がんばればMinecraftレベルぐらいまで作りこめると思う
↓
選択肢#2
- ゲームは諦め、Nekoだけを使って、普通のアプリを作る。
アプリなら毎フレーム描画する必要はないので、GCはそこまで多発しないし悪影響も少ない。
便利で面白ければLINEみたいに大流行するかも?
(Nekoは、Clojureで普通のAndroidアプリを書く為のフレームワーク)
↓
選択肢#3
- 通常のJavaによるAndroidアプリ開発と同様のテクニックを用いてカリカリにチューニングできるDSLを、マクロで構築する。
その上で、ぬるぬる動くAndroidネイティブゲームを作る。
パズドラみたいに人気が出たらいいね
↓
選択肢#4
- マクロを使って、前述の各問題(cons不可、関数呼び出し重い)を回避したLisp処理系をClojure上に構築する。
その上で楽にぬるぬる動くゲームを作る。
GCを自前で用意する必要あり。高難易度
まとめ
- とりあえず、まともな速度で動作するゲームが作れた
- ただしAndroid実機でまともな速度で動かすには、Javaと同程度のチューニング労力をかける必要がある
- Android実機で動かすのを諦めてPC配布のみにするなら、普通にClojureの流儀で書いて全く問題ない。
CLANでゲーム作ってニコニコ自作ゲームフェスとかに応募してみよう!
- プログラムの実行速度が良好な事と、そのゲームが面白いかどうかという事は、直交する概念。
ぬるぬる動いてもクソゲーでは駄目です!
おまけ
プレゼン後の質問タイム、懇親会で出た質問
(憶えてる分のみ。メモ取れなかったので超うろおぼえ)
↓
「現在のAndroidではチューニング必須」との事だけど、
進化速度早いから
「端末およびDalvik VMの性能がPC並になるのを待つ」
という選択肢はどう?
- それは一般的にはアリだと思うんですが、自分は「このCLANで利益の出るゲーム/アプリを作って、可能なら会社勤務せずに暮らしていく」という事で作成したので、待っていると餓死してしまうので、自分的にはナシです!
↓
Android向けの最適化ってどんなの?
- データはJavaの構造体やarrayに格納して破壊的変更して使う
- オブジェクトは最初に大量に生成してそれを使いまわす、途中で作らない。
いわゆるJavaのprimitive数値型はオブジェクトではないので途中で作りまくっても問題ないがBigInt化とboxingに注意
- mapやreduceは、dotimesやloop~recurで代用
- 関数実行回数の多いところはマクロ/definlineでインライン化
- あとは既存のJavaでのAndroidアプリ最適化手法をぐぐって真似する!!!
(このへん当日ちゃんと全部説明できてなかったと思う)
↓
単なるconsが結構重いというのは意外
- まだ調査中なんですが、AndroidのDalvik VMではどうも、cons等のオブジェクト生成(いわゆるJavaでのnew)を行うタイミングでGCを動かす判定も行われるようです。
なのでcons自体は重くはないけれど、同時にGCが動く時があり、それで0.05秒ぐらい世界が止まり、これが毎秒60フレーム更新するゲーム等では結構な問題になる、という感じ
- 最初から大量にcons cell確保して自前で管理できればいいけど、残念ながらClojureの標準のcons cell(というかsequence)はimmutableつまり変更不可!
- 何らかの抜け道がないかどうかはまだ模索中